home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Misc / RZToDoList / Source / GraphicImage.m < prev    next >
Encoding:
Text File  |  1995-06-12  |  5.9 KB  |  220 lines

  1. /* 
  2.  * GraphicImage
  3.  *
  4.  * An object for embedding images in a Text object
  5.  *
  6.  * You may freely copy, distribute and reuse the code in this example.
  7.  * This code is provided AS IS without warranty of any kind, expressed 
  8.  * or implied, as to its fitness for any particular use.
  9.  *
  10.  * Copyright 1995 Ralph Zazula (rzazula@next.com).  All Rights Reserved.
  11.  *
  12.  */
  13.  
  14. #import <dpsclient/psops.h>
  15. #import <dpsclient/wraps.h>
  16. #import <appkit/NXImage.h>
  17. #import <appkit/Text.h>
  18. #import <appkit/Window.h>
  19. #import <appkit/Application.h>
  20.  
  21. #import "GraphicImage.h"
  22.  
  23.  
  24. @implementation GraphicImage
  25.  
  26.  
  27. - initForImage:anImage
  28. {
  29.     [super init];
  30.     
  31.   /* save our graphic image */
  32.     image = anImage;
  33.     
  34.     return self;
  35. }
  36.  
  37. - free
  38. {
  39.     [image free];
  40.     return [super free];
  41. }
  42.  
  43. - calcCellSize:(NXSize *)theSize
  44. {
  45.   /* our graphic image determines our size */
  46.     [image getSize:theSize];
  47.  
  48.     return self;
  49. }
  50.  
  51. - highlight:(const NXRect *)cellFrame inView:controlView lit:(BOOL)flag
  52. {
  53.     if (highlighted != flag) {
  54.     highlighted = flag;
  55.     
  56.       /* toggle highlighting */
  57.     NXHighlightRect(cellFrame);
  58.     
  59.       /* make change visible */
  60.     [[controlView window] flushWindow];
  61.     }
  62.     
  63.     return self;
  64. }
  65.  
  66. - drawSelf:(const NXRect *)cellFrame inView:controlView
  67. {
  68.     NXPoint    point;
  69.     
  70.   /*
  71.    * the text object expects us not to modify the current graphics state, so
  72.    * we'll save it
  73.    */
  74.     PSgsave();
  75.  
  76.   /* fill our bounds with the text object's background gray (if opaque) */
  77.     if ([controlView isOpaque]) {
  78.     PSsetgray([controlView backgroundGray]);
  79.     NXRectFill(cellFrame);
  80.     }
  81.     
  82.   /* we're in a flipped coordinate system */
  83.     point = cellFrame->origin;
  84.     point.y += cellFrame->size.height;
  85.     
  86.   /* draw the image */
  87.     [image composite:NX_SOVER toPoint:&point];
  88.     
  89.   /* restore the graphics state */
  90.     PSgrestore();
  91.  
  92.     return self;
  93. }
  94.  
  95. #define DRAG_MASK (NX_MOUSEUPMASK | NX_MOUSEDRAGGEDMASK)
  96.  
  97. - trackMouse:(NXEvent *)theEvent inRect:(const NXRect *)cellFrame
  98.   ofView:controlView
  99. {
  100.     int        oldMask;
  101.     NXEvent    *event;
  102.     NXPoint    mouseLocation;
  103.     BOOL    mouseInCell = NO;
  104.     
  105.   /* we want to grab mouse dragged events */
  106.     oldMask = [[controlView window] addToEventMask:NX_MOUSEDRAGGEDMASK];
  107.     
  108.   /* start our event loop, looking for mouse-dragged or mouse-up events */
  109.     event = [NXApp getNextEvent:DRAG_MASK];
  110.     while (event->type != NX_MOUSEUP) {
  111.  
  112.       /* mouse-dragged event;  highlight if mouse is in cell bounds */
  113.     mouseLocation = event->location;
  114.     [controlView convertPoint:&mouseLocation fromView:NULL];
  115.     mouseInCell = NXPointInRect(&mouseLocation, cellFrame);
  116.     
  117.     if (mouseInCell != highlighted) {
  118.       /* we have to lock focus before calling hightlight:inView:lit: */
  119.         [controlView lockFocus];
  120.         [self highlight:cellFrame inView:controlView lit:mouseInCell];
  121.         [controlView unlockFocus];
  122.     }
  123.     event = [NXApp getNextEvent:DRAG_MASK];
  124.     }
  125.     
  126.   /* turn off any highlighting */
  127.     [controlView lockFocus];
  128.     [self highlight:cellFrame inView:controlView lit:NO];
  129.     [controlView unlockFocus];
  130.     
  131.   /* reset the event mask */
  132.     [[controlView window] setEventMask:oldMask];
  133.     
  134.   /* if a double-click and the mouse is over us, do something */
  135.     mouseLocation = event->location;
  136.     [controlView convertPoint:&mouseLocation fromView:NULL];
  137.     if (NXPointInRect(&mouseLocation, cellFrame) &&
  138.         event->data.mouse.click == 2) {
  139.     [self performDoubleClickAction];
  140.     }
  141.     
  142.     return self;
  143. }
  144.  
  145. - readRichText:(NXStream *)stream forView:view
  146. {
  147.     NXStream    *memoryStream;
  148.     int        length, i = 0;
  149.     char    highNibble, lowNibble;
  150.     
  151.   /* find out how bytes there are */
  152.     NXScanf(stream, "%d ", &length);
  153.     
  154.   /* create a place to temporarily store the reconstituted image data */
  155.     memoryStream = NXOpenMemory(NULL, 0, NX_READWRITE);
  156.     while (i < length) {
  157.         highNibble = NXGetc(stream) - ' ';
  158.         lowNibble = NXGetc(stream) - ' ';
  159.     NXPutc(memoryStream, ((highNibble << 4) + lowNibble));
  160.     i++;
  161.     }
  162.     
  163.   /* rewind and feed the data to our NXImage */
  164.     NXSeek(memoryStream, 0, NX_FROMSTART);
  165.     image = [[NXImage alloc] initFromStream:memoryStream];
  166.  
  167.     NXCloseMemory(memoryStream, NX_FREEBUFFER);
  168.  
  169.     return self;
  170. }
  171.  
  172. - writeRichText:(NXStream *)stream forView:view
  173. {
  174.     NXStream    *memoryStream;
  175.     char    nextByte, *buffer;
  176.     int        length, maxLength, i;
  177.     
  178.   /*
  179.    * This method gives us a chance to write out whatever information we
  180.    * need to recreate ourself when the text object loads the RTF back in.
  181.    * There are a couple different strategies for doing this:  placing the
  182.    * data "inline" or writing out the filename and saving the file somewhere
  183.    * else.  This method takes the first approach, converting the TIFF data to
  184.    * ASCII (7-bits) since the RTF specification requires 8-bit data to be
  185.    * escaped.  This isn't the best solution because every time we read the RTF
  186.    * file in, we have to read the data as well (which we've expanded to twice
  187.    * its original size in order to store in the RTF).  Additionally, the data's
  188.    * imbedded within the RTF (there might be occassions where we want to read
  189.    * the data, a TIFF in this case, but not the RTF).  The best approach is to
  190.    * place the data in a BTree or some other external storage and to leave some
  191.    * identifier in the RTF stream.
  192.    */
  193.  
  194.   /* get some temporary storage */
  195.     memoryStream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
  196.     [image writeTIFF:memoryStream];
  197.  
  198.   /* get a pointer to the TIFF data and remember its length in bytes */
  199.     NXGetMemoryBuffer(memoryStream, &buffer, &length, &maxLength);
  200.     NXPrintf(stream, "%d ", length);
  201.  
  202.   /* convert each byte to two ASCII characters */
  203.     for (i = 0; i < length; i++) {
  204.         nextByte = buffer[i];
  205.         NXPrintf(stream, "%c%c", ((nextByte & 0xF0) >> 4) + ' ',
  206.          (nextByte & 0x0F) + ' ');
  207.     }
  208.     
  209.     NXCloseMemory(memoryStream, NX_FREEBUFFER);
  210.     
  211.     return self;
  212. }
  213.  
  214. - performDoubleClickAction
  215. {
  216.   /* we don't do anything when the user double-clicks on us */
  217.     return self;
  218. }
  219.  
  220. @end